<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<title>CollectionViewChatLayout.swift - Slather</title>
<link href="slather.css" media="all" rel="stylesheet">
</head>
<body>
<header><div class="row"><a href="index.html"><img src="logo.jpg" alt="Slather logo"></a></div></header><div class="row"><div id="reports">
<h2 class="cov_title">
<span>Coverage for "CollectionViewChatLayout.swift" : </span><span class="cov_low">0.00%</span>
</h2>
<h4 class="cov_subtitle">(0 of 754 relevant lines covered)</h4>
<h4 class="cov_filepath">ChatLayout/Classes/Core/CollectionViewChatLayout.swift</h4>
<table class="source_code">
<tr class="never">
<td class="num">1</td>
<td class="src"><pre><code class="objc">//</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">2</td>
<td class="src"><pre><code class="objc">// ChatLayout</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">3</td>
<td class="src"><pre><code class="objc">// CollectionViewChatLayout.swift</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">4</td>
<td class="src"><pre><code class="objc">// https://github.com/ekazaev/ChatLayout</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">5</td>
<td class="src"><pre><code class="objc">//</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">6</td>
<td class="src"><pre><code class="objc">// Created by Eugene Kazaev in 2020-2023.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">7</td>
<td class="src"><pre><code class="objc">// Distributed under the MIT license.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">8</td>
<td class="src"><pre><code class="objc">//</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">9</td>
<td class="src"><pre><code class="objc">// Become a sponsor:</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">10</td>
<td class="src"><pre><code class="objc">// https://github.com/sponsors/ekazaev</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">11</td>
<td class="src"><pre><code class="objc">//</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">12</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">13</td>
<td class="src"><pre><code class="objc">import Foundation</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">14</td>
<td class="src"><pre><code class="objc">import UIKit</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">15</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">16</td>
<td class="src"><pre><code class="objc">/// A collection view layout that can display items in a grid similar to `UITableView` but aligning them</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">17</td>
<td class="src"><pre><code class="objc">/// to the leading or trailing edge of the `UICollectionView`. Helps to maintain chat like behavior by keeping</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">18</td>
<td class="src"><pre><code class="objc">/// content offset from the bottom constant. Can deal with autosizing cells and supplementary views.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">19</td>
<td class="src"><pre><code class="objc">/// ### Custom Properties:</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">20</td>
<td class="src"><pre><code class="objc">/// `CollectionViewChatLayout.delegate`</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">21</td>
<td class="src"><pre><code class="objc">///</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">22</td>
<td class="src"><pre><code class="objc">/// `CollectionViewChatLayout.settings`</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">23</td>
<td class="src"><pre><code class="objc">///</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">24</td>
<td class="src"><pre><code class="objc">/// `CollectionViewChatLayout.keepContentOffsetAtBottomOnBatchUpdates`</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">25</td>
<td class="src"><pre><code class="objc">///</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">26</td>
<td class="src"><pre><code class="objc">/// `CollectionViewChatLayout.processOnlyVisibleItemsOnAnimatedBatchUpdates`</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">27</td>
<td class="src"><pre><code class="objc">///</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">28</td>
<td class="src"><pre><code class="objc">/// `CollectionViewChatLayout.visibleBounds`</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">29</td>
<td class="src"><pre><code class="objc">///</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">30</td>
<td class="src"><pre><code class="objc">/// `CollectionViewChatLayout.layoutFrame`</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">31</td>
<td class="src"><pre><code class="objc">///</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">32</td>
<td class="src"><pre><code class="objc">/// ### Custom Methods:</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">33</td>
<td class="src"><pre><code class="objc">/// `CollectionViewChatLayout.getContentOffsetSnapshot(...)`</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">34</td>
<td class="src"><pre><code class="objc">///</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">35</td>
<td class="src"><pre><code class="objc">/// `CollectionViewChatLayout.restoreContentOffset(...)`</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">36</td>
<td class="src"><pre><code class="objc">public final class CollectionViewChatLayout: UICollectionViewLayout {</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">37</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">38</td>
<td class="src"><pre><code class="objc">    // MARK: Custom Properties</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">39</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">40</td>
<td class="src"><pre><code class="objc">    /// `CollectionViewChatLayout` delegate.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">41</td>
<td class="src"><pre><code class="objc">    public weak var delegate: ChatLayoutDelegate?</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">42</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">43</td>
<td class="src"><pre><code class="objc">    /// Additional settings for `CollectionViewChatLayout`.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">44</td>
<td class="src"><pre><code class="objc">    public var settings = ChatLayoutSettings() {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">45</td>
<td class="src"><pre><code class="objc">        didSet {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">46</td>
<td class="src"><pre><code class="objc">            guard collectionView != nil,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">47</td>
<td class="src"><pre><code class="objc">                  settings != oldValue else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">48</td>
<td class="src"><pre><code class="objc">                return</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">49</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">50</td>
<td class="src"><pre><code class="objc">            invalidateLayout()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">51</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">52</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">53</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">54</td>
<td class="src"><pre><code class="objc">    /// Default `UIScrollView` behaviour is to keep content offset constant from the top edge. If this flag is set to `true`</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">55</td>
<td class="src"><pre><code class="objc">    /// `CollectionViewChatLayout` should try to compensate batch update changes to keep the current content at the bottom of the visible</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">56</td>
<td class="src"><pre><code class="objc">    /// part of `UICollectionView`.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">57</td>
<td class="src"><pre><code class="objc">    ///</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">58</td>
<td class="src"><pre><code class="objc">    /// **NB:**</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">59</td>
<td class="src"><pre><code class="objc">    /// Keep in mind that if during the batch content inset changes also (e.g. keyboard frame changes), `CollectionViewChatLayout` will usually get that information after</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">60</td>
<td class="src"><pre><code class="objc">    /// the animation starts and wont be able to compensate that change too. It should be done manually.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">61</td>
<td class="src"><pre><code class="objc">    public var keepContentOffsetAtBottomOnBatchUpdates: Bool = false</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">62</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">63</td>
<td class="src"><pre><code class="objc">    /// Sometimes `UIScrollView` can behave weirdly if there are too many corrections in it's `contentOffset` during the animation. Especially when content size of the `UIScrollView`</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">64</td>
<td class="src"><pre><code class="objc">    // is getting smaller first and then expands again as the newly appearing cells sizes are being calculated. That is why `CollectionViewChatLayout`</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">65</td>
<td class="src"><pre><code class="objc">    /// tries to process only the elements that are currently visible on the screen. But often it is not needed. This flag allows you to have fine control over this behaviour.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">66</td>
<td class="src"><pre><code class="objc">    /// It set to `true` by default to keep the compatibility with the older versions of the library.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">67</td>
<td class="src"><pre><code class="objc">    ///</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">68</td>
<td class="src"><pre><code class="objc">    /// **NB:**</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">69</td>
<td class="src"><pre><code class="objc">    /// This flag is only to provide fine control over the batch updates. If in doubts - keep it `true`.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">70</td>
<td class="src"><pre><code class="objc">    public var processOnlyVisibleItemsOnAnimatedBatchUpdates: Bool = true</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">71</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">72</td>
<td class="src"><pre><code class="objc">    /// Represent the currently visible rectangle.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">73</td>
<td class="src"><pre><code class="objc">    public var visibleBounds: CGRect {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">74</td>
<td class="src"><pre><code class="objc">        guard let collectionView else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">75</td>
<td class="src"><pre><code class="objc">            return .zero</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">76</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">77</td>
<td class="src"><pre><code class="objc">        return CGRect(x: adjustedContentInset.left,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">78</td>
<td class="src"><pre><code class="objc">                      y: collectionView.contentOffset.y + adjustedContentInset.top,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">79</td>
<td class="src"><pre><code class="objc">                      width: collectionView.bounds.width - adjustedContentInset.left - adjustedContentInset.right,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">80</td>
<td class="src"><pre><code class="objc">                      height: collectionView.bounds.height - adjustedContentInset.top - adjustedContentInset.bottom)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">81</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">82</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">83</td>
<td class="src"><pre><code class="objc">    /// Represent the rectangle where all the items are aligned.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">84</td>
<td class="src"><pre><code class="objc">    public var layoutFrame: CGRect {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">85</td>
<td class="src"><pre><code class="objc">        guard let collectionView else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">86</td>
<td class="src"><pre><code class="objc">            return .zero</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">87</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">88</td>
<td class="src"><pre><code class="objc">        let additionalInsets = settings.additionalInsets</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">89</td>
<td class="src"><pre><code class="objc">        return CGRect(x: adjustedContentInset.left + additionalInsets.left,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">90</td>
<td class="src"><pre><code class="objc">                      y: adjustedContentInset.top + additionalInsets.top,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">91</td>
<td class="src"><pre><code class="objc">                      width: collectionView.bounds.width - additionalInsets.left - additionalInsets.right - adjustedContentInset.left - adjustedContentInset.right,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">92</td>
<td class="src"><pre><code class="objc">                      height: controller.contentHeight(at: state) - additionalInsets.top - additionalInsets.bottom - adjustedContentInset.top - adjustedContentInset.bottom)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">93</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">94</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">95</td>
<td class="src"><pre><code class="objc">    // MARK: Inherited Properties</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">96</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">97</td>
<td class="src"><pre><code class="objc">    /// The direction of the language you used when designing `CollectionViewChatLayout` layout.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">98</td>
<td class="src"><pre><code class="objc">    public override var developmentLayoutDirection: UIUserInterfaceLayoutDirection {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">99</td>
<td class="src"><pre><code class="objc">        .leftToRight</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">100</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">101</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">102</td>
<td class="src"><pre><code class="objc">    /// A Boolean value that indicates whether the horizontal coordinate system is automatically flipped at appropriate times.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">103</td>
<td class="src"><pre><code class="objc">    public override var flipsHorizontallyInOppositeLayoutDirection: Bool {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">104</td>
<td class="src"><pre><code class="objc">        _flipsHorizontallyInOppositeLayoutDirection</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">105</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">106</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">107</td>
<td class="src"><pre><code class="objc">    /// Custom layoutAttributesClass is `ChatLayoutAttributes`.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">108</td>
<td class="src"><pre><code class="objc">    public override class var layoutAttributesClass: AnyClass {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">109</td>
<td class="src"><pre><code class="objc">        ChatLayoutAttributes.self</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">110</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">111</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">112</td>
<td class="src"><pre><code class="objc">    /// Custom invalidationContextClass is `ChatLayoutInvalidationContext`.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">113</td>
<td class="src"><pre><code class="objc">    public override class var invalidationContextClass: AnyClass {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">114</td>
<td class="src"><pre><code class="objc">        ChatLayoutInvalidationContext.self</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">115</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">116</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">117</td>
<td class="src"><pre><code class="objc">    /// The width and height of the collection view&rsquo;s contents.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">118</td>
<td class="src"><pre><code class="objc">    public override var collectionViewContentSize: CGSize {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">119</td>
<td class="src"><pre><code class="objc">        let contentSize: CGSize</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">120</td>
<td class="src"><pre><code class="objc">        if state == .beforeUpdate {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">121</td>
<td class="src"><pre><code class="objc">            contentSize = controller.contentSize(for: .beforeUpdate)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">122</td>
<td class="src"><pre><code class="objc">        } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">123</td>
<td class="src"><pre><code class="objc">            var size = controller.contentSize(for: .beforeUpdate)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">124</td>
<td class="src"><pre><code class="objc">            if #available(iOS 16.0, *) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">125</td>
<td class="src"><pre><code class="objc">                if controller.totalProposedCompensatingOffset &gt; 0 {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">126</td>
<td class="src"><pre><code class="objc">                    size.height += controller.totalProposedCompensatingOffset</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">127</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">128</td>
<td class="src"><pre><code class="objc">            } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">129</td>
<td class="src"><pre><code class="objc">                size.height += controller.totalProposedCompensatingOffset</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">130</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">131</td>
<td class="src"><pre><code class="objc">            contentSize = size</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">132</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">133</td>
<td class="src"><pre><code class="objc">        return contentSize</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">134</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">135</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">136</td>
<td class="src"><pre><code class="objc">    /// There is an issue in IOS 15.1 that proposed content offset is being ignored by the UICollectionView when user is scrolling.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">137</td>
<td class="src"><pre><code class="objc">    /// This flag enables a hack to compensate this offset later. You can disable it if necessary.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">138</td>
<td class="src"><pre><code class="objc">    /// Bug reported: https://feedbackassistant.apple.com/feedback/9727104</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">139</td>
<td class="src"><pre><code class="objc">    ///</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">140</td>
<td class="src"><pre><code class="objc">    /// PS: This issue was fixed in 15.2</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">141</td>
<td class="src"><pre><code class="objc">    public var enableIOS15_1Fix: Bool = true</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">142</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">143</td>
<td class="src"><pre><code class="objc">    // MARK: Internal Properties</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">144</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">145</td>
<td class="src"><pre><code class="objc">    var adjustedContentInset: UIEdgeInsets {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">146</td>
<td class="src"><pre><code class="objc">        guard let collectionView else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">147</td>
<td class="src"><pre><code class="objc">            return .zero</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">148</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">149</td>
<td class="src"><pre><code class="objc">        return collectionView.adjustedContentInset</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">150</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">151</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">152</td>
<td class="src"><pre><code class="objc">    var viewSize: CGSize {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">153</td>
<td class="src"><pre><code class="objc">        guard let collectionView else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">154</td>
<td class="src"><pre><code class="objc">            return .zero</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">155</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">156</td>
<td class="src"><pre><code class="objc">        return collectionView.frame.size</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">157</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">158</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">159</td>
<td class="src"><pre><code class="objc">    // MARK: Private Properties</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">160</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">161</td>
<td class="src"><pre><code class="objc">    private struct PrepareActions: OptionSet {</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">162</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">163</td>
<td class="src"><pre><code class="objc">        let rawValue: UInt</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">164</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">165</td>
<td class="src"><pre><code class="objc">        static let recreateSectionModels = PrepareActions(rawValue: 1 &lt;&lt; 0)</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">166</td>
<td class="src"><pre><code class="objc">        static let updateLayoutMetrics = PrepareActions(rawValue: 1 &lt;&lt; 1)</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">167</td>
<td class="src"><pre><code class="objc">        static let cachePreviousWidth = PrepareActions(rawValue: 1 &lt;&lt; 2)</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">168</td>
<td class="src"><pre><code class="objc">        static let cachePreviousContentInsets = PrepareActions(rawValue: 1 &lt;&lt; 3)</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">169</td>
<td class="src"><pre><code class="objc">        static let switchStates = PrepareActions(rawValue: 1 &lt;&lt; 4)</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">170</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">171</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">172</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">173</td>
<td class="src"><pre><code class="objc">    private struct InvalidationActions: OptionSet {</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">174</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">175</td>
<td class="src"><pre><code class="objc">        let rawValue: UInt</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">176</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">177</td>
<td class="src"><pre><code class="objc">        static let shouldInvalidateOnBoundsChange = InvalidationActions(rawValue: 1 &lt;&lt; 0)</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">178</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">179</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">180</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">181</td>
<td class="src"><pre><code class="objc">    private lazy var controller = StateController(layoutRepresentation: self)</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">182</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">183</td>
<td class="src"><pre><code class="objc">    private var state: ModelState = .beforeUpdate</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">184</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">185</td>
<td class="src"><pre><code class="objc">    private var prepareActions: PrepareActions = []</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">186</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">187</td>
<td class="src"><pre><code class="objc">    private var invalidationActions: InvalidationActions = []</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">188</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">189</td>
<td class="src"><pre><code class="objc">    private var cachedCollectionViewSize: CGSize?</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">190</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">191</td>
<td class="src"><pre><code class="objc">    private var cachedCollectionViewInset: UIEdgeInsets?</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">192</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">193</td>
<td class="src"><pre><code class="objc">    // These properties are used to keep the layout attributes copies used for insert/delete</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">194</td>
<td class="src"><pre><code class="objc">    // animations up-to-date as items are self-sized. If we don't keep these copies up-to-date, then</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">195</td>
<td class="src"><pre><code class="objc">    // animations will start from the estimated height.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">196</td>
<td class="src"><pre><code class="objc">    private var attributesForPendingAnimations = [ItemKind: [ItemPath: ChatLayoutAttributes]]()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">197</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">198</td>
<td class="src"><pre><code class="objc">    private var invalidatedAttributes = [ItemKind: Set&lt;ItemPath&gt;]()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">199</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">200</td>
<td class="src"><pre><code class="objc">    private var dontReturnAttributes: Bool = true</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">201</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">202</td>
<td class="src"><pre><code class="objc">    private var currentPositionSnapshot: ChatLayoutPositionSnapshot?</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">203</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">204</td>
<td class="src"><pre><code class="objc">    private let _flipsHorizontallyInOppositeLayoutDirection: Bool</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">205</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">206</td>
<td class="src"><pre><code class="objc">    // MARK: IOS 15.1 fix flags</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">207</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">208</td>
<td class="src"><pre><code class="objc">    private var needsIOS15_1IssueFix: Bool {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">209</td>
<td class="src"><pre><code class="objc">        guard enableIOS15_1Fix else { return false }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">210</td>
<td class="src"><pre><code class="objc">        guard #unavailable(iOS 15.2) else { return false }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">211</td>
<td class="src"><pre><code class="objc">        guard #available(iOS 15.1, *) else { return false }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">212</td>
<td class="src"><pre><code class="objc">        return isUserInitiatedScrolling &amp;&amp; !controller.isAnimatedBoundsChange</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">213</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">214</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">215</td>
<td class="src"><pre><code class="objc">    // MARK: Constructors</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">216</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">217</td>
<td class="src"><pre><code class="objc">    /// Default constructor.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">218</td>
<td class="src"><pre><code class="objc">    /// - Parameters:</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">219</td>
<td class="src"><pre><code class="objc">    ///   - flipsHorizontallyInOppositeLayoutDirection: Indicates whether the horizontal coordinate</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">220</td>
<td class="src"><pre><code class="objc">    ///     system is automatically flipped at appropriate times. In practice, this is used to support</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">221</td>
<td class="src"><pre><code class="objc">    ///     right-to-left layout.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">222</td>
<td class="src"><pre><code class="objc">    public init(flipsHorizontallyInOppositeLayoutDirection: Bool = true) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">223</td>
<td class="src"><pre><code class="objc">        _flipsHorizontallyInOppositeLayoutDirection = flipsHorizontallyInOppositeLayoutDirection</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">224</td>
<td class="src"><pre><code class="objc">        super.init()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">225</td>
<td class="src"><pre><code class="objc">        resetAttributesForPendingAnimations()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">226</td>
<td class="src"><pre><code class="objc">        resetInvalidatedAttributes()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">227</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">228</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">229</td>
<td class="src"><pre><code class="objc">    /// Returns an object initialized from data in a given unarchiver.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">230</td>
<td class="src"><pre><code class="objc">    public required init?(coder aDecoder: NSCoder) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">231</td>
<td class="src"><pre><code class="objc">        _flipsHorizontallyInOppositeLayoutDirection = true</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">232</td>
<td class="src"><pre><code class="objc">        super.init(coder: aDecoder)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">233</td>
<td class="src"><pre><code class="objc">        resetAttributesForPendingAnimations()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">234</td>
<td class="src"><pre><code class="objc">        resetInvalidatedAttributes()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">235</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">236</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">237</td>
<td class="src"><pre><code class="objc">    // MARK: Custom Methods</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">238</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">239</td>
<td class="src"><pre><code class="objc">    /// Get current offset of the item closest to the provided edge.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">240</td>
<td class="src"><pre><code class="objc">    /// - Parameter edge: The edge of the `UICollectionView`</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">241</td>
<td class="src"><pre><code class="objc">    /// - Returns: `ChatLayoutPositionSnapshot`</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">242</td>
<td class="src"><pre><code class="objc">    public func getContentOffsetSnapshot(from edge: ChatLayoutPositionSnapshot.Edge) -&gt; ChatLayoutPositionSnapshot? {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">243</td>
<td class="src"><pre><code class="objc">        guard let collectionView else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">244</td>
<td class="src"><pre><code class="objc">            return nil</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">245</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">246</td>
<td class="src"><pre><code class="objc">        let insets = UIEdgeInsets(top: -collectionView.frame.height,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">247</td>
<td class="src"><pre><code class="objc">                                  left: 0,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">248</td>
<td class="src"><pre><code class="objc">                                  bottom: -collectionView.frame.height,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">249</td>
<td class="src"><pre><code class="objc">                                  right: 0)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">250</td>
<td class="src"><pre><code class="objc">        let visibleBounds = visibleBounds</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">251</td>
<td class="src"><pre><code class="objc">        let layoutAttributes = controller.layoutAttributesForElements(in: visibleBounds.inset(by: insets),</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">252</td>
<td class="src"><pre><code class="objc">                                                                      state: state,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">253</td>
<td class="src"><pre><code class="objc">                                                                      ignoreCache: true)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">254</td>
<td class="src"><pre><code class="objc">            .sorted(by: { $0.frame.maxY &lt; $1.frame.maxY })</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">255</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">256</td>
<td class="src"><pre><code class="objc">        switch edge {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">257</td>
<td class="src"><pre><code class="objc">        case .top:</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">258</td>
<td class="src"><pre><code class="objc">            guard let firstVisibleItemAttributes = layoutAttributes.first(where: { $0.frame.minY &gt;= visibleBounds.higherPoint.y }) else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">259</td>
<td class="src"><pre><code class="objc">                return nil</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">260</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">261</td>
<td class="src"><pre><code class="objc">            let visibleBoundsTopOffset = firstVisibleItemAttributes.frame.minY - visibleBounds.higherPoint.y - settings.additionalInsets.top</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">262</td>
<td class="src"><pre><code class="objc">            return ChatLayoutPositionSnapshot(indexPath: firstVisibleItemAttributes.indexPath, kind: firstVisibleItemAttributes.kind, edge: .top, offset: visibleBoundsTopOffset)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">263</td>
<td class="src"><pre><code class="objc">        case .bottom:</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">264</td>
<td class="src"><pre><code class="objc">            guard let lastVisibleItemAttributes = layoutAttributes.last(where: { $0.frame.minY &lt;= visibleBounds.lowerPoint.y }) else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">265</td>
<td class="src"><pre><code class="objc">                return nil</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">266</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">267</td>
<td class="src"><pre><code class="objc">            let visibleBoundsBottomOffset = visibleBounds.lowerPoint.y - lastVisibleItemAttributes.frame.maxY - settings.additionalInsets.bottom</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">268</td>
<td class="src"><pre><code class="objc">            return ChatLayoutPositionSnapshot(indexPath: lastVisibleItemAttributes.indexPath, kind: lastVisibleItemAttributes.kind, edge: .bottom, offset: visibleBoundsBottomOffset)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">269</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">270</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">271</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">272</td>
<td class="src"><pre><code class="objc">    /// Invalidates layout of the `UICollectionView` and trying to keep the offset of the item provided in `ChatLayoutPositionSnapshot`</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">273</td>
<td class="src"><pre><code class="objc">    /// - Parameter snapshot: `ChatLayoutPositionSnapshot`</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">274</td>
<td class="src"><pre><code class="objc">    public func restoreContentOffset(with snapshot: ChatLayoutPositionSnapshot) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">275</td>
<td class="src"><pre><code class="objc">        guard let collectionView else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">276</td>
<td class="src"><pre><code class="objc">            return</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">277</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">278</td>
<td class="src"><pre><code class="objc">        collectionView.setNeedsLayout()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">279</td>
<td class="src"><pre><code class="objc">        collectionView.layoutIfNeeded()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">280</td>
<td class="src"><pre><code class="objc">        currentPositionSnapshot = snapshot</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">281</td>
<td class="src"><pre><code class="objc">        let context = ChatLayoutInvalidationContext()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">282</td>
<td class="src"><pre><code class="objc">        context.invalidateLayoutMetrics = false</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">283</td>
<td class="src"><pre><code class="objc">        invalidateLayout(with: context)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">284</td>
<td class="src"><pre><code class="objc">        collectionView.setNeedsLayout()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">285</td>
<td class="src"><pre><code class="objc">        collectionView.layoutIfNeeded()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">286</td>
<td class="src"><pre><code class="objc">        currentPositionSnapshot = nil</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">287</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">288</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">289</td>
<td class="src"><pre><code class="objc">    // MARK: Providing Layout Attributes</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">290</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">291</td>
<td class="src"><pre><code class="objc">    /// Tells the layout object to update the current layout.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">292</td>
<td class="src"><pre><code class="objc">    public override func prepare() {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">293</td>
<td class="src"><pre><code class="objc">        super.prepare()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">294</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">295</td>
<td class="src"><pre><code class="objc">        guard let collectionView,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">296</td>
<td class="src"><pre><code class="objc">              !prepareActions.isEmpty else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">297</td>
<td class="src"><pre><code class="objc">            return</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">298</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">299</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">300</td>
<td class="src"><pre><code class="objc">        #if DEBUG</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">301</td>
<td class="src"><pre><code class="objc">        if collectionView.isPrefetchingEnabled {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">302</td>
<td class="src"><pre><code class="objc">            preconditionFailure("UICollectionView with prefetching enabled is not supported due to https://openradar.appspot.com/40926834 bug.")</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">303</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">304</td>
<td class="src"><pre><code class="objc">        #endif</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">305</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">306</td>
<td class="src"><pre><code class="objc">        if prepareActions.contains(.switchStates) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">307</td>
<td class="src"><pre><code class="objc">            controller.commitUpdates()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">308</td>
<td class="src"><pre><code class="objc">            state = .beforeUpdate</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">309</td>
<td class="src"><pre><code class="objc">            resetAttributesForPendingAnimations()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">310</td>
<td class="src"><pre><code class="objc">            resetInvalidatedAttributes()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">311</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">312</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">313</td>
<td class="src"><pre><code class="objc">        if prepareActions.contains(.recreateSectionModels) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">314</td>
<td class="src"><pre><code class="objc">            var sections: ContiguousArray&lt;SectionModel&lt;CollectionViewChatLayout&gt;&gt; = []</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">315</td>
<td class="src"><pre><code class="objc">            for sectionIndex in 0..&lt;collectionView.numberOfSections {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">316</td>
<td class="src"><pre><code class="objc">                // Header</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">317</td>
<td class="src"><pre><code class="objc">                let header: ItemModel?</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">318</td>
<td class="src"><pre><code class="objc">                if delegate?.shouldPresentHeader(self, at: sectionIndex) == true {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">319</td>
<td class="src"><pre><code class="objc">                    let headerPath = IndexPath(item: 0, section: sectionIndex)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">320</td>
<td class="src"><pre><code class="objc">                    header = ItemModel(with: configuration(for: .header, at: headerPath))</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">321</td>
<td class="src"><pre><code class="objc">                } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">322</td>
<td class="src"><pre><code class="objc">                    header = nil</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">323</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">324</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">325</td>
<td class="src"><pre><code class="objc">                // Items</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">326</td>
<td class="src"><pre><code class="objc">                var items: ContiguousArray&lt;ItemModel&gt; = []</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">327</td>
<td class="src"><pre><code class="objc">                for itemIndex in 0..&lt;collectionView.numberOfItems(inSection: sectionIndex) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">328</td>
<td class="src"><pre><code class="objc">                    let itemPath = IndexPath(item: itemIndex, section: sectionIndex)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">329</td>
<td class="src"><pre><code class="objc">                    items.append(ItemModel(with: configuration(for: .cell, at: itemPath)))</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">330</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">331</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">332</td>
<td class="src"><pre><code class="objc">                // Footer</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">333</td>
<td class="src"><pre><code class="objc">                let footer: ItemModel?</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">334</td>
<td class="src"><pre><code class="objc">                if delegate?.shouldPresentFooter(self, at: sectionIndex) == true {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">335</td>
<td class="src"><pre><code class="objc">                    let footerPath = IndexPath(item: 0, section: sectionIndex)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">336</td>
<td class="src"><pre><code class="objc">                    footer = ItemModel(with: configuration(for: .footer, at: footerPath))</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">337</td>
<td class="src"><pre><code class="objc">                } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">338</td>
<td class="src"><pre><code class="objc">                    footer = nil</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">339</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">340</td>
<td class="src"><pre><code class="objc">                var section = SectionModel(header: header, footer: footer, items: items, collectionLayout: self)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">341</td>
<td class="src"><pre><code class="objc">                section.assembleLayout()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">342</td>
<td class="src"><pre><code class="objc">                sections.append(section)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">343</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">344</td>
<td class="src"><pre><code class="objc">            controller.set(sections, at: .beforeUpdate)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">345</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">346</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">347</td>
<td class="src"><pre><code class="objc">        if prepareActions.contains(.updateLayoutMetrics),</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">348</td>
<td class="src"><pre><code class="objc">           !prepareActions.contains(.recreateSectionModels) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">349</td>
<td class="src"><pre><code class="objc">            var sections: ContiguousArray&lt;SectionModel&gt; = controller.layout(at: state).sections</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">350</td>
<td class="src"><pre><code class="objc">            sections.withUnsafeMutableBufferPointer { directlyMutableSections in</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">351</td>
<td class="src"><pre><code class="objc">                for sectionIndex in 0..&lt;directlyMutableSections.count {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">352</td>
<td class="src"><pre><code class="objc">                    var section = directlyMutableSections[sectionIndex]</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">353</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">354</td>
<td class="src"><pre><code class="objc">                    // Header</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">355</td>
<td class="src"><pre><code class="objc">                    if var header = section.header {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">356</td>
<td class="src"><pre><code class="objc">                        header.resetSize()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">357</td>
<td class="src"><pre><code class="objc">                        section.set(header: header)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">358</td>
<td class="src"><pre><code class="objc">                    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">359</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">360</td>
<td class="src"><pre><code class="objc">                    // Items</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">361</td>
<td class="src"><pre><code class="objc">                    var items: ContiguousArray&lt;ItemModel&gt; = section.items</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">362</td>
<td class="src"><pre><code class="objc">                    items.withUnsafeMutableBufferPointer { directlyMutableItems in</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">363</td>
<td class="src"><pre><code class="objc">                        DispatchQueue.concurrentPerform(iterations: directlyMutableItems.count, execute: { rowIndex in</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">364</td>
<td class="src"><pre><code class="objc">                            directlyMutableItems[rowIndex].resetSize()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">365</td>
<td class="src"><pre><code class="objc">                        })</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">366</td>
<td class="src"><pre><code class="objc">                    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">367</td>
<td class="src"><pre><code class="objc">                    section.set(items: items)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">368</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">369</td>
<td class="src"><pre><code class="objc">                    // Footer</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">370</td>
<td class="src"><pre><code class="objc">                    if var footer = section.footer {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">371</td>
<td class="src"><pre><code class="objc">                        footer.resetSize()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">372</td>
<td class="src"><pre><code class="objc">                        section.set(footer: footer)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">373</td>
<td class="src"><pre><code class="objc">                    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">374</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">375</td>
<td class="src"><pre><code class="objc">                    section.assembleLayout()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">376</td>
<td class="src"><pre><code class="objc">                    directlyMutableSections[sectionIndex] = section</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">377</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">378</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">379</td>
<td class="src"><pre><code class="objc">            controller.set(sections, at: state)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">380</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">381</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">382</td>
<td class="src"><pre><code class="objc">        if prepareActions.contains(.cachePreviousContentInsets) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">383</td>
<td class="src"><pre><code class="objc">            cachedCollectionViewInset = adjustedContentInset</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">384</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">385</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">386</td>
<td class="src"><pre><code class="objc">        if prepareActions.contains(.cachePreviousWidth) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">387</td>
<td class="src"><pre><code class="objc">            cachedCollectionViewSize = collectionView.bounds.size</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">388</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">389</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">390</td>
<td class="src"><pre><code class="objc">        prepareActions = []</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">391</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">392</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">393</td>
<td class="src"><pre><code class="objc">    /// Retrieves the layout attributes for all of the cells and views in the specified rectangle.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">394</td>
<td class="src"><pre><code class="objc">    public override func layoutAttributesForElements(in rect: CGRect) -&gt; [UICollectionViewLayoutAttributes]? {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">395</td>
<td class="src"><pre><code class="objc">        // This early return prevents an issue that causes overlapping / misplaced elements after an</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">396</td>
<td class="src"><pre><code class="objc">        // off-screen batch update occurs. The root cause of this issue is that `UICollectionView`</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">397</td>
<td class="src"><pre><code class="objc">        // expects `layoutAttributesForElementsInRect:` to return post-batch-update layout attributes</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">398</td>
<td class="src"><pre><code class="objc">        // immediately after an update is sent to the collection view via the insert/delete/reload/move</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">399</td>
<td class="src"><pre><code class="objc">        // functions. Unfortunately, this is impossible - when batch updates occur, `invalidateLayout:`</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">400</td>
<td class="src"><pre><code class="objc">        // is invoked immediately with a context that has `invalidateDataSourceCounts` set to `true`.</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">401</td>
<td class="src"><pre><code class="objc">        // At this time, `CollectionViewChatLayout` has no way of knowing the details of this data source count</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">402</td>
<td class="src"><pre><code class="objc">        // change (where the insert/delete/move took place). `CollectionViewChatLayout` only gets this additional</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">403</td>
<td class="src"><pre><code class="objc">        // information once `prepareForCollectionViewUpdates:` is invoked. At that time, we're able to</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">404</td>
<td class="src"><pre><code class="objc">        // update our layout's source of truth, the `StateController`, which allows us to resolve the</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">405</td>
<td class="src"><pre><code class="objc">        // post-batch-update layout and return post-batch-update layout attributes from this function.</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">406</td>
<td class="src"><pre><code class="objc">        // Between the time that `invalidateLayout:` is invoked with `invalidateDataSourceCounts` set to</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">407</td>
<td class="src"><pre><code class="objc">        // `true`, and when `prepareForCollectionViewUpdates:` is invoked with details of the updates,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">408</td>
<td class="src"><pre><code class="objc">        // `layoutAttributesForElementsInRect:` is invoked with the expectation that we already have a</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">409</td>
<td class="src"><pre><code class="objc">        // fully resolved layout. If we return incorrect layout attributes at that time, then we'll have</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">410</td>
<td class="src"><pre><code class="objc">        // overlapping elements / visual defects. To prevent this, we can return `nil` in this</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">411</td>
<td class="src"><pre><code class="objc">        // situation, which works around the bug.</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">412</td>
<td class="src"><pre><code class="objc">        // `UICollectionViewCompositionalLayout`, in classic UIKit fashion, avoids this bug / feature by</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">413</td>
<td class="src"><pre><code class="objc">        // implementing the private function</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">414</td>
<td class="src"><pre><code class="objc">        // `_prepareForCollectionViewUpdates:withDataSourceTranslator:`, which provides the layout with</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">415</td>
<td class="src"><pre><code class="objc">        // details about the updates to the collection view before `layoutAttributesForElementsInRect:`</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">416</td>
<td class="src"><pre><code class="objc">        // is invoked, enabling them to resolve their layout in time.</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">417</td>
<td class="src"><pre><code class="objc">        guard !dontReturnAttributes else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">418</td>
<td class="src"><pre><code class="objc">            return nil</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">419</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">420</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">421</td>
<td class="src"><pre><code class="objc">        let visibleAttributes = controller.layoutAttributesForElements(in: rect, state: state)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">422</td>
<td class="src"><pre><code class="objc">        return visibleAttributes</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">423</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">424</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">425</td>
<td class="src"><pre><code class="objc">    /// Retrieves layout information for an item at the specified index path with a corresponding cell.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">426</td>
<td class="src"><pre><code class="objc">    public override func layoutAttributesForItem(at indexPath: IndexPath) -&gt; UICollectionViewLayoutAttributes? {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">427</td>
<td class="src"><pre><code class="objc">        guard !dontReturnAttributes else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">428</td>
<td class="src"><pre><code class="objc">            return nil</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">429</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">430</td>
<td class="src"><pre><code class="objc">        let attributes = controller.itemAttributes(for: indexPath.itemPath, kind: .cell, at: state)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">431</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">432</td>
<td class="src"><pre><code class="objc">        return attributes</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">433</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">434</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">435</td>
<td class="src"><pre><code class="objc">    /// Retrieves the layout attributes for the specified supplementary view.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">436</td>
<td class="src"><pre><code class="objc">    public override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -&gt; UICollectionViewLayoutAttributes? {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">437</td>
<td class="src"><pre><code class="objc">        guard !dontReturnAttributes else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">438</td>
<td class="src"><pre><code class="objc">            return nil</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">439</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">440</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">441</td>
<td class="src"><pre><code class="objc">        let kind = ItemKind(elementKind)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">442</td>
<td class="src"><pre><code class="objc">        let attributes = controller.itemAttributes(for: indexPath.itemPath, kind: kind, at: state)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">443</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">444</td>
<td class="src"><pre><code class="objc">        return attributes</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">445</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">446</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">447</td>
<td class="src"><pre><code class="objc">    // MARK: Coordinating Animated Changes</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">448</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">449</td>
<td class="src"><pre><code class="objc">    /// Prepares the layout object for animated changes to the view&rsquo;s bounds or the insertion or deletion of items.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">450</td>
<td class="src"><pre><code class="objc">    public override func prepare(forAnimatedBoundsChange oldBounds: CGRect) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">451</td>
<td class="src"><pre><code class="objc">        controller.isAnimatedBoundsChange = true</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">452</td>
<td class="src"><pre><code class="objc">        controller.process(changeItems: [])</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">453</td>
<td class="src"><pre><code class="objc">        state = .afterUpdate</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">454</td>
<td class="src"><pre><code class="objc">        prepareActions.remove(.switchStates)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">455</td>
<td class="src"><pre><code class="objc">        guard let collectionView,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">456</td>
<td class="src"><pre><code class="objc">              oldBounds.width != collectionView.bounds.width,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">457</td>
<td class="src"><pre><code class="objc">              keepContentOffsetAtBottomOnBatchUpdates,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">458</td>
<td class="src"><pre><code class="objc">              controller.isLayoutBiggerThanVisibleBounds(at: state) else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">459</td>
<td class="src"><pre><code class="objc">            return</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">460</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">461</td>
<td class="src"><pre><code class="objc">        let newBounds = collectionView.bounds</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">462</td>
<td class="src"><pre><code class="objc">        let heightDifference = oldBounds.height - newBounds.height</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">463</td>
<td class="src"><pre><code class="objc">        controller.proposedCompensatingOffset += heightDifference + (oldBounds.origin.y - newBounds.origin.y)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">464</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">465</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">466</td>
<td class="src"><pre><code class="objc">    /// Cleans up after any animated changes to the view&rsquo;s bounds or after the insertion or deletion of items.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">467</td>
<td class="src"><pre><code class="objc">    public override func finalizeAnimatedBoundsChange() {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">468</td>
<td class="src"><pre><code class="objc">        if controller.isAnimatedBoundsChange {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">469</td>
<td class="src"><pre><code class="objc">            state = .beforeUpdate</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">470</td>
<td class="src"><pre><code class="objc">            resetInvalidatedAttributes()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">471</td>
<td class="src"><pre><code class="objc">            resetAttributesForPendingAnimations()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">472</td>
<td class="src"><pre><code class="objc">            controller.commitUpdates()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">473</td>
<td class="src"><pre><code class="objc">            controller.isAnimatedBoundsChange = false</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">474</td>
<td class="src"><pre><code class="objc">            controller.proposedCompensatingOffset = 0</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">475</td>
<td class="src"><pre><code class="objc">            controller.batchUpdateCompensatingOffset = 0</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">476</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">477</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">478</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">479</td>
<td class="src"><pre><code class="objc">    // MARK: Context Invalidation</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">480</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">481</td>
<td class="src"><pre><code class="objc">    /// Asks the layout object if changes to a self-sizing cell require a layout update.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">482</td>
<td class="src"><pre><code class="objc">    public override func shouldInvalidateLayout(forPreferredLayoutAttributes preferredAttributes: UICollectionViewLayoutAttributes, withOriginalAttributes originalAttributes: UICollectionViewLayoutAttributes) -&gt; Bool {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">483</td>
<td class="src"><pre><code class="objc">        let preferredAttributesItemPath = preferredAttributes.indexPath.itemPath</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">484</td>
<td class="src"><pre><code class="objc">        guard let preferredMessageAttributes = preferredAttributes as? ChatLayoutAttributes,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">485</td>
<td class="src"><pre><code class="objc">              let item = controller.item(for: preferredAttributesItemPath, kind: preferredMessageAttributes.kind, at: state) else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">486</td>
<td class="src"><pre><code class="objc">            return true</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">487</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">488</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">489</td>
<td class="src"><pre><code class="objc">        let shouldInvalidateLayout = item.calculatedSize == nil || item.alignment != preferredMessageAttributes.alignment</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">490</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">491</td>
<td class="src"><pre><code class="objc">        return shouldInvalidateLayout</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">492</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">493</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">494</td>
<td class="src"><pre><code class="objc">    /// Retrieves a context object that identifies the portions of the layout that should change in response to dynamic cell changes.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">495</td>
<td class="src"><pre><code class="objc">    public override func invalidationContext(forPreferredLayoutAttributes preferredAttributes: UICollectionViewLayoutAttributes, withOriginalAttributes originalAttributes: UICollectionViewLayoutAttributes) -&gt; UICollectionViewLayoutInvalidationContext {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">496</td>
<td class="src"><pre><code class="objc">        guard let preferredMessageAttributes = preferredAttributes as? ChatLayoutAttributes else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">497</td>
<td class="src"><pre><code class="objc">            return super.invalidationContext(forPreferredLayoutAttributes: preferredAttributes, withOriginalAttributes: originalAttributes)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">498</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">499</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">500</td>
<td class="src"><pre><code class="objc">        let preferredAttributesItemPath = preferredMessageAttributes.indexPath.itemPath</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">501</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">502</td>
<td class="src"><pre><code class="objc">        if state == .afterUpdate {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">503</td>
<td class="src"><pre><code class="objc">            invalidatedAttributes[preferredMessageAttributes.kind]?.insert(preferredAttributesItemPath)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">504</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">505</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">506</td>
<td class="src"><pre><code class="objc">        let layoutAttributesForPendingAnimation = attributesForPendingAnimations[preferredMessageAttributes.kind]?[preferredAttributesItemPath]</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">507</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">508</td>
<td class="src"><pre><code class="objc">        let newItemSize = itemSize(with: preferredMessageAttributes)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">509</td>
<td class="src"><pre><code class="objc">        let newItemAlignment: ChatItemAlignment</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">510</td>
<td class="src"><pre><code class="objc">        if controller.reloadedIndexes.contains(preferredMessageAttributes.indexPath) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">511</td>
<td class="src"><pre><code class="objc">            newItemAlignment = alignment(for: preferredMessageAttributes.kind, at: preferredMessageAttributes.indexPath)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">512</td>
<td class="src"><pre><code class="objc">        } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">513</td>
<td class="src"><pre><code class="objc">            newItemAlignment = preferredMessageAttributes.alignment</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">514</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">515</td>
<td class="src"><pre><code class="objc">        controller.update(preferredSize: newItemSize,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">516</td>
<td class="src"><pre><code class="objc">                          alignment: newItemAlignment,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">517</td>
<td class="src"><pre><code class="objc">                          for: preferredAttributesItemPath,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">518</td>
<td class="src"><pre><code class="objc">                          kind: preferredMessageAttributes.kind,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">519</td>
<td class="src"><pre><code class="objc">                          at: state)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">520</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">521</td>
<td class="src"><pre><code class="objc">        let context = super.invalidationContext(forPreferredLayoutAttributes: preferredMessageAttributes, withOriginalAttributes: originalAttributes) as! ChatLayoutInvalidationContext</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">522</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">523</td>
<td class="src"><pre><code class="objc">        let heightDifference = newItemSize.height - originalAttributes.size.height</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">524</td>
<td class="src"><pre><code class="objc">        let isAboveBottomEdge = originalAttributes.frame.minY.rounded() &lt;= visibleBounds.maxY.rounded()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">525</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">526</td>
<td class="src"><pre><code class="objc">        if heightDifference != 0,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">527</td>
<td class="src"><pre><code class="objc">           (keepContentOffsetAtBottomOnBatchUpdates &amp;&amp; controller.contentHeight(at: state).rounded() + heightDifference &gt; visibleBounds.height.rounded()) || isUserInitiatedScrolling,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">528</td>
<td class="src"><pre><code class="objc">           isAboveBottomEdge {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">529</td>
<td class="src"><pre><code class="objc">            context.contentOffsetAdjustment.y += heightDifference</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">530</td>
<td class="src"><pre><code class="objc">            invalidationActions.formUnion([.shouldInvalidateOnBoundsChange])</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">531</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">532</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">533</td>
<td class="src"><pre><code class="objc">        if let attributes = controller.itemAttributes(for: preferredAttributesItemPath, kind: preferredMessageAttributes.kind, at: state)?.typedCopy() {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">534</td>
<td class="src"><pre><code class="objc">            layoutAttributesForPendingAnimation?.frame = attributes.frame</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">535</td>
<td class="src"><pre><code class="objc">            if state == .afterUpdate {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">536</td>
<td class="src"><pre><code class="objc">                controller.totalProposedCompensatingOffset += heightDifference</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">537</td>
<td class="src"><pre><code class="objc">                controller.offsetByTotalCompensation(attributes: layoutAttributesForPendingAnimation, for: state, backward: true)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">538</td>
<td class="src"><pre><code class="objc">                if controller.insertedIndexes.contains(preferredMessageAttributes.indexPath) ||</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">539</td>
<td class="src"><pre><code class="objc">                    controller.insertedSectionsIndexes.contains(preferredMessageAttributes.indexPath.section) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">540</td>
<td class="src"><pre><code class="objc">                    layoutAttributesForPendingAnimation.map { attributes in</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">541</td>
<td class="src"><pre><code class="objc">                        guard let delegate else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">542</td>
<td class="src"><pre><code class="objc">                            attributes.alpha = 0</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">543</td>
<td class="src"><pre><code class="objc">                            return</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">544</td>
<td class="src"><pre><code class="objc">                        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">545</td>
<td class="src"><pre><code class="objc">                        delegate.initialLayoutAttributesForInsertedItem(self, of: .cell, at: attributes.indexPath, modifying: attributes, on: .invalidation)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">546</td>
<td class="src"><pre><code class="objc">                    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">547</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">548</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">549</td>
<td class="src"><pre><code class="objc">        } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">550</td>
<td class="src"><pre><code class="objc">            layoutAttributesForPendingAnimation?.frame.size = newItemSize</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">551</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">552</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">553</td>
<td class="src"><pre><code class="objc">        if #available(iOS 13.0, *) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">554</td>
<td class="src"><pre><code class="objc">            switch preferredMessageAttributes.kind {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">555</td>
<td class="src"><pre><code class="objc">            case .cell:</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">556</td>
<td class="src"><pre><code class="objc">                context.invalidateItems(at: [preferredMessageAttributes.indexPath])</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">557</td>
<td class="src"><pre><code class="objc">            case .header, .footer:</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">558</td>
<td class="src"><pre><code class="objc">                context.invalidateSupplementaryElements(ofKind: preferredMessageAttributes.kind.supplementaryElementStringType, at: [preferredMessageAttributes.indexPath])</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">559</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">560</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">561</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">562</td>
<td class="src"><pre><code class="objc">        context.invalidateLayoutMetrics = false</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">563</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">564</td>
<td class="src"><pre><code class="objc">        return context</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">565</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">566</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">567</td>
<td class="src"><pre><code class="objc">    /// Asks the layout object if the new bounds require a layout update.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">568</td>
<td class="src"><pre><code class="objc">    public override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -&gt; Bool {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">569</td>
<td class="src"><pre><code class="objc">        let shouldInvalidateLayout = cachedCollectionViewSize != .some(newBounds.size) ||</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">570</td>
<td class="src"><pre><code class="objc">            cachedCollectionViewInset != .some(adjustedContentInset) ||</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">571</td>
<td class="src"><pre><code class="objc">            invalidationActions.contains(.shouldInvalidateOnBoundsChange)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">572</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">573</td>
<td class="src"><pre><code class="objc">        invalidationActions.remove(.shouldInvalidateOnBoundsChange)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">574</td>
<td class="src"><pre><code class="objc">        return shouldInvalidateLayout</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">575</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">576</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">577</td>
<td class="src"><pre><code class="objc">    /// Retrieves a context object that defines the portions of the layout that should change when a bounds change occurs.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">578</td>
<td class="src"><pre><code class="objc">    public override func invalidationContext(forBoundsChange newBounds: CGRect) -&gt; UICollectionViewLayoutInvalidationContext {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">579</td>
<td class="src"><pre><code class="objc">        let invalidationContext = super.invalidationContext(forBoundsChange: newBounds) as! ChatLayoutInvalidationContext</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">580</td>
<td class="src"><pre><code class="objc">        invalidationContext.invalidateLayoutMetrics = false</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">581</td>
<td class="src"><pre><code class="objc">        return invalidationContext</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">582</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">583</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">584</td>
<td class="src"><pre><code class="objc">    /// Invalidates the current layout using the information in the provided context object.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">585</td>
<td class="src"><pre><code class="objc">    public override func invalidateLayout(with context: UICollectionViewLayoutInvalidationContext) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">586</td>
<td class="src"><pre><code class="objc">        guard let collectionView else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">587</td>
<td class="src"><pre><code class="objc">            super.invalidateLayout(with: context)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">588</td>
<td class="src"><pre><code class="objc">            return</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">589</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">590</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">591</td>
<td class="src"><pre><code class="objc">        guard let context = context as? ChatLayoutInvalidationContext else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">592</td>
<td class="src"><pre><code class="objc">            assertionFailure("`context` must be an instance of `ChatLayoutInvalidationContext`.")</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">593</td>
<td class="src"><pre><code class="objc">            return</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">594</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">595</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">596</td>
<td class="src"><pre><code class="objc">        controller.resetCachedAttributes()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">597</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">598</td>
<td class="src"><pre><code class="objc">        dontReturnAttributes = context.invalidateDataSourceCounts &amp;&amp; !context.invalidateEverything</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">599</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">600</td>
<td class="src"><pre><code class="objc">        if context.invalidateEverything {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">601</td>
<td class="src"><pre><code class="objc">            prepareActions.formUnion([.recreateSectionModels])</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">602</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">603</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">604</td>
<td class="src"><pre><code class="objc">        // Checking `cachedCollectionViewWidth != collectionView.bounds.size.width` is necessary</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">605</td>
<td class="src"><pre><code class="objc">        // because the collection view's width can change without a `contentSizeAdjustment` occurring.</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">606</td>
<td class="src"><pre><code class="objc">        if context.contentSizeAdjustment.width != 0 || cachedCollectionViewSize != collectionView.bounds.size {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">607</td>
<td class="src"><pre><code class="objc">            prepareActions.formUnion([.cachePreviousWidth])</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">608</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">609</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">610</td>
<td class="src"><pre><code class="objc">        if cachedCollectionViewInset != adjustedContentInset {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">611</td>
<td class="src"><pre><code class="objc">            prepareActions.formUnion([.cachePreviousContentInsets])</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">612</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">613</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">614</td>
<td class="src"><pre><code class="objc">        if context.invalidateLayoutMetrics, !context.invalidateDataSourceCounts {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">615</td>
<td class="src"><pre><code class="objc">            prepareActions.formUnion([.updateLayoutMetrics])</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">616</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">617</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">618</td>
<td class="src"><pre><code class="objc">        if let currentPositionSnapshot {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">619</td>
<td class="src"><pre><code class="objc">            let contentHeight = controller.contentHeight(at: state)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">620</td>
<td class="src"><pre><code class="objc">            if let frame = controller.itemFrame(for: currentPositionSnapshot.indexPath.itemPath, kind: currentPositionSnapshot.kind, at: state, isFinal: true),</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">621</td>
<td class="src"><pre><code class="objc">               contentHeight != 0,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">622</td>
<td class="src"><pre><code class="objc">               contentHeight &gt; visibleBounds.size.height {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">623</td>
<td class="src"><pre><code class="objc">                switch currentPositionSnapshot.edge {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">624</td>
<td class="src"><pre><code class="objc">                case .top:</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">625</td>
<td class="src"><pre><code class="objc">                    let desiredOffset = frame.minY - currentPositionSnapshot.offset - collectionView.adjustedContentInset.top - settings.additionalInsets.top</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">626</td>
<td class="src"><pre><code class="objc">                    context.contentOffsetAdjustment.y = desiredOffset - collectionView.contentOffset.y</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">627</td>
<td class="src"><pre><code class="objc">                case .bottom:</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">628</td>
<td class="src"><pre><code class="objc">                    let maxAllowed = max(-collectionView.adjustedContentInset.top, contentHeight - collectionView.frame.height + collectionView.adjustedContentInset.bottom)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">629</td>
<td class="src"><pre><code class="objc">                    let desiredOffset = max(min(maxAllowed, frame.maxY + currentPositionSnapshot.offset - collectionView.bounds.height + collectionView.adjustedContentInset.bottom + settings.additionalInsets.bottom), -collectionView.adjustedContentInset.top)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">630</td>
<td class="src"><pre><code class="objc">                    context.contentOffsetAdjustment.y = desiredOffset - collectionView.contentOffset.y</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">631</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">632</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">633</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">634</td>
<td class="src"><pre><code class="objc">        super.invalidateLayout(with: context)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">635</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">636</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">637</td>
<td class="src"><pre><code class="objc">    /// Invalidates the current layout and triggers a layout update.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">638</td>
<td class="src"><pre><code class="objc">    public override func invalidateLayout() {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">639</td>
<td class="src"><pre><code class="objc">        super.invalidateLayout()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">640</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">641</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">642</td>
<td class="src"><pre><code class="objc">    /// Retrieves the content offset to use after an animated layout update or change.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">643</td>
<td class="src"><pre><code class="objc">    public override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -&gt; CGPoint {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">644</td>
<td class="src"><pre><code class="objc">        if controller.proposedCompensatingOffset != 0,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">645</td>
<td class="src"><pre><code class="objc">           let collectionView {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">646</td>
<td class="src"><pre><code class="objc">            let minPossibleContentOffset = -collectionView.adjustedContentInset.top</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">647</td>
<td class="src"><pre><code class="objc">            let newProposedContentOffset = CGPoint(x: proposedContentOffset.x, y: max(minPossibleContentOffset, min(proposedContentOffset.y + controller.proposedCompensatingOffset, maxPossibleContentOffset.y)))</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">648</td>
<td class="src"><pre><code class="objc">            invalidationActions.formUnion([.shouldInvalidateOnBoundsChange])</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">649</td>
<td class="src"><pre><code class="objc">            if needsIOS15_1IssueFix {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">650</td>
<td class="src"><pre><code class="objc">                controller.proposedCompensatingOffset = 0</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">651</td>
<td class="src"><pre><code class="objc">                collectionView.contentOffset = newProposedContentOffset</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">652</td>
<td class="src"><pre><code class="objc">                return newProposedContentOffset</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">653</td>
<td class="src"><pre><code class="objc">            } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">654</td>
<td class="src"><pre><code class="objc">                controller.proposedCompensatingOffset = 0</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">655</td>
<td class="src"><pre><code class="objc">                return newProposedContentOffset</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">656</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">657</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">658</td>
<td class="src"><pre><code class="objc">        return super.targetContentOffset(forProposedContentOffset: proposedContentOffset)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">659</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">660</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">661</td>
<td class="src"><pre><code class="objc">    // MARK: Responding to Collection View Updates</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">662</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">663</td>
<td class="src"><pre><code class="objc">    /// Notifies the layout object that the contents of the collection view are about to change.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">664</td>
<td class="src"><pre><code class="objc">    public override func prepare(forCollectionViewUpdates updateItems: [UICollectionViewUpdateItem]) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">665</td>
<td class="src"><pre><code class="objc">        let changeItems = updateItems.compactMap { ChangeItem(with: $0) }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">666</td>
<td class="src"><pre><code class="objc">        controller.process(changeItems: changeItems)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">667</td>
<td class="src"><pre><code class="objc">        state = .afterUpdate</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">668</td>
<td class="src"><pre><code class="objc">        dontReturnAttributes = false</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">669</td>
<td class="src"><pre><code class="objc">        super.prepare(forCollectionViewUpdates: updateItems)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">670</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">671</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">672</td>
<td class="src"><pre><code class="objc">    /// Performs any additional animations or clean up needed during a collection view update.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">673</td>
<td class="src"><pre><code class="objc">    public override func finalizeCollectionViewUpdates() {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">674</td>
<td class="src"><pre><code class="objc">        controller.proposedCompensatingOffset = 0</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">675</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">676</td>
<td class="src"><pre><code class="objc">        if keepContentOffsetAtBottomOnBatchUpdates,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">677</td>
<td class="src"><pre><code class="objc">           controller.isLayoutBiggerThanVisibleBounds(at: state),</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">678</td>
<td class="src"><pre><code class="objc">           controller.batchUpdateCompensatingOffset != 0,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">679</td>
<td class="src"><pre><code class="objc">           let collectionView {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">680</td>
<td class="src"><pre><code class="objc">            let compensatingOffset: CGFloat</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">681</td>
<td class="src"><pre><code class="objc">            if controller.contentSize(for: .beforeUpdate).height &gt; visibleBounds.size.height {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">682</td>
<td class="src"><pre><code class="objc">                compensatingOffset = controller.batchUpdateCompensatingOffset</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">683</td>
<td class="src"><pre><code class="objc">            } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">684</td>
<td class="src"><pre><code class="objc">                compensatingOffset = maxPossibleContentOffset.y - collectionView.contentOffset.y</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">685</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">686</td>
<td class="src"><pre><code class="objc">            controller.batchUpdateCompensatingOffset = 0</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">687</td>
<td class="src"><pre><code class="objc">            let context = ChatLayoutInvalidationContext()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">688</td>
<td class="src"><pre><code class="objc">            context.contentOffsetAdjustment.y = compensatingOffset</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">689</td>
<td class="src"><pre><code class="objc">            invalidateLayout(with: context)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">690</td>
<td class="src"><pre><code class="objc">        } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">691</td>
<td class="src"><pre><code class="objc">            controller.batchUpdateCompensatingOffset = 0</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">692</td>
<td class="src"><pre><code class="objc">            let context = ChatLayoutInvalidationContext()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">693</td>
<td class="src"><pre><code class="objc">            invalidateLayout(with: context)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">694</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">695</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">696</td>
<td class="src"><pre><code class="objc">        prepareActions.formUnion(.switchStates)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">697</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">698</td>
<td class="src"><pre><code class="objc">        super.finalizeCollectionViewUpdates()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">699</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">700</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">701</td>
<td class="src"><pre><code class="objc">    // MARK: - Cell Appearance Animation</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">702</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">703</td>
<td class="src"><pre><code class="objc">    /// Retrieves the starting layout information for an item being inserted into the collection view.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">704</td>
<td class="src"><pre><code class="objc">    public override func initialLayoutAttributesForAppearingItem(at itemIndexPath: IndexPath) -&gt; UICollectionViewLayoutAttributes? {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">705</td>
<td class="src"><pre><code class="objc">        var attributes: ChatLayoutAttributes?</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">706</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">707</td>
<td class="src"><pre><code class="objc">        let itemPath = itemIndexPath.itemPath</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">708</td>
<td class="src"><pre><code class="objc">        if state == .afterUpdate {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">709</td>
<td class="src"><pre><code class="objc">            if controller.insertedIndexes.contains(itemIndexPath) || controller.insertedSectionsIndexes.contains(itemPath.section) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">710</td>
<td class="src"><pre><code class="objc">                attributes = controller.itemAttributes(for: itemPath, kind: .cell, at: .afterUpdate)?.typedCopy()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">711</td>
<td class="src"><pre><code class="objc">                controller.offsetByTotalCompensation(attributes: attributes, for: state, backward: true)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">712</td>
<td class="src"><pre><code class="objc">                attributes.map { attributes in</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">713</td>
<td class="src"><pre><code class="objc">                    guard let delegate else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">714</td>
<td class="src"><pre><code class="objc">                        attributes.alpha = 0</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">715</td>
<td class="src"><pre><code class="objc">                        return</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">716</td>
<td class="src"><pre><code class="objc">                    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">717</td>
<td class="src"><pre><code class="objc">                    delegate.initialLayoutAttributesForInsertedItem(self, of: .cell, at: itemIndexPath, modifying: attributes, on: .initial)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">718</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">719</td>
<td class="src"><pre><code class="objc">                attributesForPendingAnimations[.cell]?[itemPath] = attributes</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">720</td>
<td class="src"><pre><code class="objc">            } else if let itemIdentifier = controller.itemIdentifier(for: itemPath, kind: .cell, at: .afterUpdate),</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">721</td>
<td class="src"><pre><code class="objc">                      let initialIndexPath = controller.itemPath(by: itemIdentifier, kind: .cell, at: .beforeUpdate) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">722</td>
<td class="src"><pre><code class="objc">                attributes = controller.itemAttributes(for: initialIndexPath, kind: .cell, at: .beforeUpdate)?.typedCopy() ?? ChatLayoutAttributes(forCellWith: itemIndexPath)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">723</td>
<td class="src"><pre><code class="objc">                attributes?.indexPath = itemIndexPath</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">724</td>
<td class="src"><pre><code class="objc">                if #unavailable(iOS 13.0) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">725</td>
<td class="src"><pre><code class="objc">                    if controller.reloadedIndexes.contains(itemIndexPath) || controller.reloadedSectionsIndexes.contains(itemPath.section) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">726</td>
<td class="src"><pre><code class="objc">                        // It is needed to position the new cell in the middle of the old cell on ios 12</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">727</td>
<td class="src"><pre><code class="objc">                        attributesForPendingAnimations[.cell]?[itemPath] = attributes</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">728</td>
<td class="src"><pre><code class="objc">                    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">729</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">730</td>
<td class="src"><pre><code class="objc">            } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">731</td>
<td class="src"><pre><code class="objc">                attributes = controller.itemAttributes(for: itemPath, kind: .cell, at: .beforeUpdate)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">732</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">733</td>
<td class="src"><pre><code class="objc">        } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">734</td>
<td class="src"><pre><code class="objc">            attributes = controller.itemAttributes(for: itemPath, kind: .cell, at: .beforeUpdate)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">735</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">736</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">737</td>
<td class="src"><pre><code class="objc">        return attributes</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">738</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">739</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">740</td>
<td class="src"><pre><code class="objc">    /// Retrieves the final layout information for an item that is about to be removed from the collection view.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">741</td>
<td class="src"><pre><code class="objc">    public override func finalLayoutAttributesForDisappearingItem(at itemIndexPath: IndexPath) -&gt; UICollectionViewLayoutAttributes? {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">742</td>
<td class="src"><pre><code class="objc">        var attributes: ChatLayoutAttributes?</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">743</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">744</td>
<td class="src"><pre><code class="objc">        let itemPath = itemIndexPath.itemPath</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">745</td>
<td class="src"><pre><code class="objc">        if state == .afterUpdate {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">746</td>
<td class="src"><pre><code class="objc">            if controller.deletedIndexes.contains(itemIndexPath) || controller.deletedSectionsIndexes.contains(itemPath.section) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">747</td>
<td class="src"><pre><code class="objc">                attributes = controller.itemAttributes(for: itemPath, kind: .cell, at: .beforeUpdate)?.typedCopy() ?? ChatLayoutAttributes(forCellWith: itemIndexPath)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">748</td>
<td class="src"><pre><code class="objc">                controller.offsetByTotalCompensation(attributes: attributes, for: state, backward: false)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">749</td>
<td class="src"><pre><code class="objc">                if keepContentOffsetAtBottomOnBatchUpdates,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">750</td>
<td class="src"><pre><code class="objc">                   controller.isLayoutBiggerThanVisibleBounds(at: state),</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">751</td>
<td class="src"><pre><code class="objc">                   let attributes {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">752</td>
<td class="src"><pre><code class="objc">                    attributes.frame = attributes.frame.offsetBy(dx: 0, dy: attributes.frame.height * 0.2)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">753</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">754</td>
<td class="src"><pre><code class="objc">                attributes.map { attributes in</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">755</td>
<td class="src"><pre><code class="objc">                    guard let delegate else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">756</td>
<td class="src"><pre><code class="objc">                        attributes.alpha = 0</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">757</td>
<td class="src"><pre><code class="objc">                        return</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">758</td>
<td class="src"><pre><code class="objc">                    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">759</td>
<td class="src"><pre><code class="objc">                    delegate.finalLayoutAttributesForDeletedItem(self, of: .cell, at: itemIndexPath, modifying: attributes)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">760</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">761</td>
<td class="src"><pre><code class="objc">            } else if let itemIdentifier = controller.itemIdentifier(for: itemPath, kind: .cell, at: .beforeUpdate),</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">762</td>
<td class="src"><pre><code class="objc">                      let finalIndexPath = controller.itemPath(by: itemIdentifier, kind: .cell, at: .afterUpdate) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">763</td>
<td class="src"><pre><code class="objc">                if controller.movedIndexes.contains(itemIndexPath) || controller.movedSectionsIndexes.contains(itemPath.section) ||</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">764</td>
<td class="src"><pre><code class="objc">                    controller.reloadedIndexes.contains(itemIndexPath) || controller.reloadedSectionsIndexes.contains(itemPath.section) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">765</td>
<td class="src"><pre><code class="objc">                    attributes = controller.itemAttributes(for: finalIndexPath, kind: .cell, at: .afterUpdate)?.typedCopy()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">766</td>
<td class="src"><pre><code class="objc">                } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">767</td>
<td class="src"><pre><code class="objc">                    attributes = controller.itemAttributes(for: itemPath, kind: .cell, at: .beforeUpdate)?.typedCopy()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">768</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">769</td>
<td class="src"><pre><code class="objc">                if invalidatedAttributes[.cell]?.contains(itemPath) ?? false {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">770</td>
<td class="src"><pre><code class="objc">                    attributes = nil</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">771</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">772</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">773</td>
<td class="src"><pre><code class="objc">                attributes?.indexPath = itemIndexPath</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">774</td>
<td class="src"><pre><code class="objc">                attributesForPendingAnimations[.cell]?[itemPath] = attributes</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">775</td>
<td class="src"><pre><code class="objc">                if controller.reloadedIndexes.contains(itemIndexPath) || controller.reloadedSectionsIndexes.contains(itemPath.section) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">776</td>
<td class="src"><pre><code class="objc">                    attributes?.alpha = 0</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">777</td>
<td class="src"><pre><code class="objc">                    attributes?.transform = CGAffineTransform(scaleX: 0, y: 0)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">778</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">779</td>
<td class="src"><pre><code class="objc">            } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">780</td>
<td class="src"><pre><code class="objc">                attributes = controller.itemAttributes(for: itemPath, kind: .cell, at: .beforeUpdate)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">781</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">782</td>
<td class="src"><pre><code class="objc">        } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">783</td>
<td class="src"><pre><code class="objc">            attributes = controller.itemAttributes(for: itemPath, kind: .cell, at: .beforeUpdate)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">784</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">785</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">786</td>
<td class="src"><pre><code class="objc">        return attributes</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">787</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">788</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">789</td>
<td class="src"><pre><code class="objc">    // MARK: - Supplementary View Appearance Animation</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">790</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">791</td>
<td class="src"><pre><code class="objc">    /// Retrieves the starting layout information for a supplementary view being inserted into the collection view.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">792</td>
<td class="src"><pre><code class="objc">    public override func initialLayoutAttributesForAppearingSupplementaryElement(ofKind elementKind: String, at elementIndexPath: IndexPath) -&gt; UICollectionViewLayoutAttributes? {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">793</td>
<td class="src"><pre><code class="objc">        var attributes: ChatLayoutAttributes?</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">794</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">795</td>
<td class="src"><pre><code class="objc">        let kind = ItemKind(elementKind)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">796</td>
<td class="src"><pre><code class="objc">        let elementPath = elementIndexPath.itemPath</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">797</td>
<td class="src"><pre><code class="objc">        if state == .afterUpdate {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">798</td>
<td class="src"><pre><code class="objc">            if controller.insertedSectionsIndexes.contains(elementPath.section) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">799</td>
<td class="src"><pre><code class="objc">                attributes = controller.itemAttributes(for: elementPath, kind: kind, at: .afterUpdate)?.typedCopy()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">800</td>
<td class="src"><pre><code class="objc">                controller.offsetByTotalCompensation(attributes: attributes, for: state, backward: true)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">801</td>
<td class="src"><pre><code class="objc">                attributes.map { attributes in</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">802</td>
<td class="src"><pre><code class="objc">                    guard let delegate else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">803</td>
<td class="src"><pre><code class="objc">                        attributes.alpha = 0</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">804</td>
<td class="src"><pre><code class="objc">                        return</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">805</td>
<td class="src"><pre><code class="objc">                    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">806</td>
<td class="src"><pre><code class="objc">                    delegate.initialLayoutAttributesForInsertedItem(self, of: kind, at: elementIndexPath, modifying: attributes, on: .initial)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">807</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">808</td>
<td class="src"><pre><code class="objc">                attributesForPendingAnimations[kind]?[elementPath] = attributes</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">809</td>
<td class="src"><pre><code class="objc">            } else if let itemIdentifier = controller.itemIdentifier(for: elementPath, kind: kind, at: .afterUpdate),</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">810</td>
<td class="src"><pre><code class="objc">                      let initialIndexPath = controller.itemPath(by: itemIdentifier, kind: kind, at: .beforeUpdate) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">811</td>
<td class="src"><pre><code class="objc">                attributes = controller.itemAttributes(for: initialIndexPath, kind: kind, at: .beforeUpdate)?.typedCopy() ?? ChatLayoutAttributes(forSupplementaryViewOfKind: elementKind, with: elementIndexPath)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">812</td>
<td class="src"><pre><code class="objc">                attributes?.indexPath = elementIndexPath</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">813</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">814</td>
<td class="src"><pre><code class="objc">                if #unavailable(iOS 13.0) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">815</td>
<td class="src"><pre><code class="objc">                    if controller.reloadedSectionsIndexes.contains(elementPath.section) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">816</td>
<td class="src"><pre><code class="objc">                        // It is needed to position the new cell in the middle of the old cell on ios 12</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">817</td>
<td class="src"><pre><code class="objc">                        attributesForPendingAnimations[kind]?[elementPath] = attributes</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">818</td>
<td class="src"><pre><code class="objc">                    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">819</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">820</td>
<td class="src"><pre><code class="objc">            } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">821</td>
<td class="src"><pre><code class="objc">                attributes = controller.itemAttributes(for: elementPath, kind: kind, at: .beforeUpdate)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">822</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">823</td>
<td class="src"><pre><code class="objc">        } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">824</td>
<td class="src"><pre><code class="objc">            attributes = controller.itemAttributes(for: elementPath, kind: kind, at: .beforeUpdate)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">825</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">826</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">827</td>
<td class="src"><pre><code class="objc">        return attributes</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">828</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">829</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">830</td>
<td class="src"><pre><code class="objc">    /// Retrieves the final layout information for a supplementary view that is about to be removed from the collection view.</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">831</td>
<td class="src"><pre><code class="objc">    public override func finalLayoutAttributesForDisappearingSupplementaryElement(ofKind elementKind: String, at elementIndexPath: IndexPath) -&gt; UICollectionViewLayoutAttributes? {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">832</td>
<td class="src"><pre><code class="objc">        var attributes: ChatLayoutAttributes?</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">833</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">834</td>
<td class="src"><pre><code class="objc">        let kind = ItemKind(elementKind)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">835</td>
<td class="src"><pre><code class="objc">        let elementPath = elementIndexPath.itemPath</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">836</td>
<td class="src"><pre><code class="objc">        if state == .afterUpdate {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">837</td>
<td class="src"><pre><code class="objc">            if controller.deletedSectionsIndexes.contains(elementPath.section) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">838</td>
<td class="src"><pre><code class="objc">                attributes = controller.itemAttributes(for: elementPath, kind: kind, at: .beforeUpdate)?.typedCopy() ?? ChatLayoutAttributes(forSupplementaryViewOfKind: elementKind, with: elementIndexPath)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">839</td>
<td class="src"><pre><code class="objc">                controller.offsetByTotalCompensation(attributes: attributes, for: state, backward: false)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">840</td>
<td class="src"><pre><code class="objc">                if keepContentOffsetAtBottomOnBatchUpdates,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">841</td>
<td class="src"><pre><code class="objc">                   controller.isLayoutBiggerThanVisibleBounds(at: state),</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">842</td>
<td class="src"><pre><code class="objc">                   let attributes {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">843</td>
<td class="src"><pre><code class="objc">                    attributes.frame = attributes.frame.offsetBy(dx: 0, dy: attributes.frame.height * 0.2)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">844</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">845</td>
<td class="src"><pre><code class="objc">                attributes.map { attributes in</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">846</td>
<td class="src"><pre><code class="objc">                    guard let delegate else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">847</td>
<td class="src"><pre><code class="objc">                        attributes.alpha = 0</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">848</td>
<td class="src"><pre><code class="objc">                        return</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">849</td>
<td class="src"><pre><code class="objc">                    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">850</td>
<td class="src"><pre><code class="objc">                    delegate.finalLayoutAttributesForDeletedItem(self, of: .cell, at: elementIndexPath, modifying: attributes)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">851</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">852</td>
<td class="src"><pre><code class="objc">            } else if let itemIdentifier = controller.itemIdentifier(for: elementPath, kind: kind, at: .beforeUpdate),</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">853</td>
<td class="src"><pre><code class="objc">                      let finalIndexPath = controller.itemPath(by: itemIdentifier, kind: kind, at: .afterUpdate) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">854</td>
<td class="src"><pre><code class="objc">                if controller.movedSectionsIndexes.contains(elementPath.section) || controller.reloadedSectionsIndexes.contains(elementPath.section) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">855</td>
<td class="src"><pre><code class="objc">                    attributes = controller.itemAttributes(for: finalIndexPath, kind: kind, at: .afterUpdate)?.typedCopy()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">856</td>
<td class="src"><pre><code class="objc">                } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">857</td>
<td class="src"><pre><code class="objc">                    attributes = controller.itemAttributes(for: elementPath, kind: kind, at: .beforeUpdate)?.typedCopy()</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">858</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">859</td>
<td class="src"><pre><code class="objc">                if invalidatedAttributes[kind]?.contains(elementPath) ?? false {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">860</td>
<td class="src"><pre><code class="objc">                    attributes = nil</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">861</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">862</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">863</td>
<td class="src"><pre><code class="objc">                attributes?.indexPath = elementIndexPath</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">864</td>
<td class="src"><pre><code class="objc">                attributesForPendingAnimations[kind]?[elementPath] = attributes</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">865</td>
<td class="src"><pre><code class="objc">                if controller.reloadedSectionsIndexes.contains(elementPath.section) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">866</td>
<td class="src"><pre><code class="objc">                    attributes?.alpha = 0</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">867</td>
<td class="src"><pre><code class="objc">                    attributes?.transform = CGAffineTransform(scaleX: 0, y: 0)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">868</td>
<td class="src"><pre><code class="objc">                }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">869</td>
<td class="src"><pre><code class="objc">            } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">870</td>
<td class="src"><pre><code class="objc">                attributes = controller.itemAttributes(for: elementPath, kind: kind, at: .beforeUpdate)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">871</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">872</td>
<td class="src"><pre><code class="objc">        } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">873</td>
<td class="src"><pre><code class="objc">            attributes = controller.itemAttributes(for: elementPath, kind: kind, at: .beforeUpdate)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">874</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">875</td>
<td class="src"><pre><code class="objc">        return attributes</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">876</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">877</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">878</td>
<td class="src"><pre><code class="objc">}</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">879</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">880</td>
<td class="src"><pre><code class="objc">extension CollectionViewChatLayout {</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">881</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">882</td>
<td class="src"><pre><code class="objc">    func configuration(for element: ItemKind, at indexPath: IndexPath) -&gt; ItemModel.Configuration {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">883</td>
<td class="src"><pre><code class="objc">        let itemSize = estimatedSize(for: element, at: indexPath)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">884</td>
<td class="src"><pre><code class="objc">        return ItemModel.Configuration(alignment: alignment(for: element, at: indexPath), preferredSize: itemSize.estimated, calculatedSize: itemSize.exact)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">885</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">886</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">887</td>
<td class="src"><pre><code class="objc">    private func estimatedSize(for element: ItemKind, at indexPath: IndexPath) -&gt; (estimated: CGSize, exact: CGSize?) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">888</td>
<td class="src"><pre><code class="objc">        guard let delegate else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">889</td>
<td class="src"><pre><code class="objc">            return (estimated: estimatedItemSize, exact: nil)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">890</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">891</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">892</td>
<td class="src"><pre><code class="objc">        let itemSize = delegate.sizeForItem(self, of: element, at: indexPath)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">893</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">894</td>
<td class="src"><pre><code class="objc">        switch itemSize {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">895</td>
<td class="src"><pre><code class="objc">        case .auto:</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">896</td>
<td class="src"><pre><code class="objc">            return (estimated: estimatedItemSize, exact: nil)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">897</td>
<td class="src"><pre><code class="objc">        case let .estimated(size):</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">898</td>
<td class="src"><pre><code class="objc">            return (estimated: size, exact: nil)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">899</td>
<td class="src"><pre><code class="objc">        case let .exact(size):</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">900</td>
<td class="src"><pre><code class="objc">            return (estimated: size, exact: size)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">901</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">902</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">903</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">904</td>
<td class="src"><pre><code class="objc">    private func itemSize(with preferredAttributes: ChatLayoutAttributes) -&gt; CGSize {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">905</td>
<td class="src"><pre><code class="objc">        let itemSize: CGSize</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">906</td>
<td class="src"><pre><code class="objc">        if let delegate,</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">907</td>
<td class="src"><pre><code class="objc">           case let .exact(size) = delegate.sizeForItem(self, of: preferredAttributes.kind, at: preferredAttributes.indexPath) {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">908</td>
<td class="src"><pre><code class="objc">            itemSize = size</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">909</td>
<td class="src"><pre><code class="objc">        } else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">910</td>
<td class="src"><pre><code class="objc">            itemSize = preferredAttributes.size</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">911</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">912</td>
<td class="src"><pre><code class="objc">        return itemSize</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">913</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">914</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">915</td>
<td class="src"><pre><code class="objc">    private func alignment(for element: ItemKind, at indexPath: IndexPath) -&gt; ChatItemAlignment {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">916</td>
<td class="src"><pre><code class="objc">        guard let delegate else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">917</td>
<td class="src"><pre><code class="objc">            return .fullWidth</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">918</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">919</td>
<td class="src"><pre><code class="objc">        return delegate.alignmentForItem(self, of: element, at: indexPath)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">920</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">921</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">922</td>
<td class="src"><pre><code class="objc">    private var estimatedItemSize: CGSize {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">923</td>
<td class="src"><pre><code class="objc">        guard let estimatedItemSize = settings.estimatedItemSize else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">924</td>
<td class="src"><pre><code class="objc">            guard collectionView != nil else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">925</td>
<td class="src"><pre><code class="objc">                return .zero</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">926</td>
<td class="src"><pre><code class="objc">            }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">927</td>
<td class="src"><pre><code class="objc">            return CGSize(width: layoutFrame.width, height: 40)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">928</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">929</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">930</td>
<td class="src"><pre><code class="objc">        return estimatedItemSize</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">931</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">932</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">933</td>
<td class="src"><pre><code class="objc">    private func resetAttributesForPendingAnimations() {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">934</td>
<td class="src"><pre><code class="objc">        ItemKind.allCases.forEach {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">935</td>
<td class="src"><pre><code class="objc">            attributesForPendingAnimations[$0] = [:]</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">936</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">937</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">938</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">939</td>
<td class="src"><pre><code class="objc">    private func resetInvalidatedAttributes() {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">940</td>
<td class="src"><pre><code class="objc">        ItemKind.allCases.forEach {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">941</td>
<td class="src"><pre><code class="objc">            invalidatedAttributes[$0] = []</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">942</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">943</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">944</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">945</td>
<td class="src"><pre><code class="objc">}</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">946</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">947</td>
<td class="src"><pre><code class="objc">extension CollectionViewChatLayout: ChatLayoutRepresentation {</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">948</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">949</td>
<td class="src"><pre><code class="objc">    func numberOfItems(in section: Int) -&gt; Int {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">950</td>
<td class="src"><pre><code class="objc">        guard let collectionView else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">951</td>
<td class="src"><pre><code class="objc">            return .zero</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">952</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">953</td>
<td class="src"><pre><code class="objc">        return collectionView.numberOfItems(inSection: section)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">954</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">955</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">956</td>
<td class="src"><pre><code class="objc">    func shouldPresentHeader(at sectionIndex: Int) -&gt; Bool {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">957</td>
<td class="src"><pre><code class="objc">        delegate?.shouldPresentHeader(self, at: sectionIndex) ?? false</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">958</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">959</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">960</td>
<td class="src"><pre><code class="objc">    func shouldPresentFooter(at sectionIndex: Int) -&gt; Bool {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">961</td>
<td class="src"><pre><code class="objc">        delegate?.shouldPresentFooter(self, at: sectionIndex) ?? false</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">962</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">963</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">964</td>
<td class="src"><pre><code class="objc">}</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">965</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">966</td>
<td class="src"><pre><code class="objc">extension CollectionViewChatLayout {</code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">967</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">968</td>
<td class="src"><pre><code class="objc">    private var maxPossibleContentOffset: CGPoint {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">969</td>
<td class="src"><pre><code class="objc">        guard let collectionView else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">970</td>
<td class="src"><pre><code class="objc">            return .zero</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">971</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">972</td>
<td class="src"><pre><code class="objc">        let maxContentOffset = max(0 - collectionView.adjustedContentInset.top, controller.contentHeight(at: state) - collectionView.frame.height + collectionView.adjustedContentInset.bottom)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">973</td>
<td class="src"><pre><code class="objc">        return CGPoint(x: 0, y: maxContentOffset)</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">974</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">975</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="missed">
<td class="num">976</td>
<td class="src"><pre><code class="objc">    private var isUserInitiatedScrolling: Bool {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">977</td>
<td class="src"><pre><code class="objc">        guard let collectionView else {</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">978</td>
<td class="src"><pre><code class="objc">            return false</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">979</td>
<td class="src"><pre><code class="objc">        }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">980</td>
<td class="src"><pre><code class="objc">        return collectionView.isDragging || collectionView.isDecelerating</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="missed">
<td class="num">981</td>
<td class="src"><pre><code class="objc">    }</code></pre></td>
<td class="coverage">!</td>
</tr>
<tr class="never">
<td class="num">982</td>
<td class="src"><pre><code class="objc"></code></pre></td>
<td class="coverage"></td>
</tr>
<tr class="never">
<td class="num">983</td>
<td class="src"><pre><code class="objc">}</code></pre></td>
<td class="coverage"></td>
</tr>
</table>
</div></div>
<footer><div class="row">
<p><a href="https://github.com/SlatherOrg/slather">Fork me on Github</a></p>
<p>&copy; 2023 Slather</p>
</div></footer><script src="highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script>
</body>
</html>
